﻿using System;
using System.Collections.Generic;
using Drill.Core;
using NUnit.Framework;

namespace Drill.Configuration
{
	[TestFixture]
	public class ConfigurationHelperFactoryTests
	{
		[Test]
		public void CanConstruct()
		{
			// Arrange
			// Nothing to arrange.

			// Act
			IConfigurationHelperFactory factory = new ConfigurationHelperFactory();

			// Assert
			Assert.That(factory, Is.Not.Null);
		}

		[Test]
		public void CanCreateInstanceWithSinglePathProviderAndExplicitNullSearchPaths()
		{
			// Arrange
			IRootPathProvider pathProvider = new ExecutingDirectoryRootPathProvider();
			List<ISearchPath> searchPaths = null;
			IConfigurationHelperFactory factory = new ConfigurationHelperFactory();

			// Act
			// ReSharper disable ExpressionIsAlwaysNull
			IConfigurationHelper configurationHelper = factory.CreateConfigurationHelper(pathProvider, searchPaths);
			// ReSharper restore ExpressionIsAlwaysNull

			// Arrange
			Assert.That(configurationHelper, Is.Not.Null);
		}

		[Test]
		public void CanCreateInstanceWithSinglePathProviderAndOmittedSearchPaths()
		{
			// Arrange
			IRootPathProvider pathProvider = new ExecutingDirectoryRootPathProvider();
			IConfigurationHelperFactory factory = new ConfigurationHelperFactory();

			// Act
			// ReSharper disable ExpressionIsAlwaysNull
			IConfigurationHelper configurationHelper = factory.CreateConfigurationHelper(pathProvider);
			// ReSharper restore ExpressionIsAlwaysNull

			// Arrange
			Assert.That(configurationHelper, Is.Not.Null);
		}

		[Test]
		public void CanCreateInstanceWithSinglePathProviderAndSearchPaths()
		{
			// Arrange
			IRootPathProvider pathProvider = new ExecutingDirectoryRootPathProvider();
			List<ISearchPath> searchPaths = new List<ISearchPath> { new SearchPath { Value = @"SomeFakeDirectory\Config" } };
			IConfigurationHelperFactory factory = new ConfigurationHelperFactory();

			// Act
			// ReSharper disable ExpressionIsAlwaysNull
			IConfigurationHelper configurationHelper = factory.CreateConfigurationHelper(pathProvider, searchPaths);
			// ReSharper restore ExpressionIsAlwaysNull

			// Arrange
			Assert.That(configurationHelper, Is.Not.Null);
		}

		[ExpectedException(typeof(ArgumentNullException), ExpectedMessage = "rootPathProvider", MatchType = MessageMatch.Contains)]
		[Test]
		public void CannotCreateInstanceWithNullPathProvider()
		{
			// Arrange
			IRootPathProvider pathProvider = null;
			IConfigurationHelperFactory factory = new ConfigurationHelperFactory();

			// Act
			// ReSharper disable ExpressionIsAlwaysNull
			factory.CreateConfigurationHelper(pathProvider);
			// ReSharper restore ExpressionIsAlwaysNull

			// Arrange
			// Nothing to assert because the test should throw an expected exception (see ExpectedException attribute).
		}

		[Test]
		public void CanCreateInstanceWithListOfPathProviderAndExplicitNullSearchPaths()
		{
			// Arrange
			List<IRootPathProvider> pathProviders = 
				new List<IRootPathProvider>
					{
						new ExecutingDirectoryRootPathProvider()
					};
			List<ISearchPath> searchPaths = null;
			IConfigurationHelperFactory factory = new ConfigurationHelperFactory();

			// Act
			// ReSharper disable ExpressionIsAlwaysNull
			IConfigurationHelper configurationHelper = factory.CreateConfigurationHelper(pathProviders, searchPaths);
			// ReSharper restore ExpressionIsAlwaysNull

			// Arrange
			Assert.That(configurationHelper, Is.Not.Null);
		}

		[Test]
		public void CanCreateInstanceWithListOfPathProviderAndOmittedSearchPaths()
		{
			// Arrange
			List<IRootPathProvider> pathProviders = 
				new List<IRootPathProvider>
					{
						new ExecutingDirectoryRootPathProvider()
					};
			IConfigurationHelperFactory factory = new ConfigurationHelperFactory();

			// Act
			// ReSharper disable ExpressionIsAlwaysNull
			IConfigurationHelper configurationHelper = factory.CreateConfigurationHelper(pathProviders);
			// ReSharper restore ExpressionIsAlwaysNull

			// Arrange
			Assert.That(configurationHelper, Is.Not.Null);
		}

		[Test]
		public void CanCreateInstanceWithListOfPathProvideSearchPaths()
		{
			// Arrange
			List<IRootPathProvider> pathProviders = 
				new List<IRootPathProvider>
					{
						new ExecutingDirectoryRootPathProvider()
					};
			List<ISearchPath> searchPaths = new List<ISearchPath> { new SearchPath { Value = @"SomeFakeDirectory\Config" } };
			IConfigurationHelperFactory factory = new ConfigurationHelperFactory();

			// Act
			// ReSharper disable ExpressionIsAlwaysNull
			IConfigurationHelper configurationHelper = factory.CreateConfigurationHelper(pathProviders, searchPaths);
			// ReSharper restore ExpressionIsAlwaysNull

			// Arrange
			Assert.That(configurationHelper, Is.Not.Null);
		}

		[ExpectedException(typeof(ArgumentNullException), ExpectedMessage = "rootPathProviders", MatchType = MessageMatch.Contains)]
		[Test]
		public void CannotCreateInstanceWithNullListOfPathProvider()
		{
			// Arrange
			List<IRootPathProvider> pathProviders = null;
			IConfigurationHelperFactory factory = new ConfigurationHelperFactory();

			// Act
			// ReSharper disable ExpressionIsAlwaysNull
			factory.CreateConfigurationHelper(pathProviders);
			// ReSharper restore ExpressionIsAlwaysNull

			// Arrange
			// Nothing to assert because the test should throw an expected exception (see ExpectedException attribute).
		}

		[ExpectedException(typeof(ArgumentException), ExpectedMessage = "rootPathProviders list is empty", MatchType = MessageMatch.Contains)]
		[Test]
		public void CannotCreateInstanceWithEmptyListOfPathProvider()
		{
			// Arrange
			List<IRootPathProvider> pathProviders = new List<IRootPathProvider>();
			IConfigurationHelperFactory factory = new ConfigurationHelperFactory();

			// Act
			// ReSharper disable ExpressionIsAlwaysNull
			factory.CreateConfigurationHelper(pathProviders);
			// ReSharper restore ExpressionIsAlwaysNull

			// Arrange
			// Nothing to assert because the test should throw an expected exception (see ExpectedException attribute).
		}
	}
}